package com.jww.dao;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

//操作数据库的公共类
public class BaseDao {

    /* ========================= 1. 数据库连接四要素 ========================= */
    private static String driver;   // JDBC 驱动类名（如 com.mysql.cj.jdbc.Driver）
    private static String url;      // 数据库 URL（如 jdbc:mysql://localhost:3306/test）
    private static String username; // 连接用户名
    private static String password; // 连接密码

    /* ========================= 2. 静态代码块 =========================
     * 类第一次被加载到 JVM 时执行，且仅执行一次。
     * 负责读取 classpath 下的 db.properties 文件，并初始化上面的四个静态变量。
     */
    static {
        // 用于承载 *.properties 文件内容的容器
        Properties properties = new Properties();

        /* 通过类加载器读取 resources 目录（或 classpath 任意目录）中的 db.properties
         * 注意：路径不要以 "/" 开头，表示从 classpath 根目录开始查找
         * 放在 Maven/Gradle 项目的 src/main/resources 下即可
         */
        InputStream is = BaseDao.class.getClassLoader()
                .getResourceAsStream("db.properties");

        try {
            // 将文件中的键值对一次性加载到 Properties 对象中
            properties.load(is);
        } catch (IOException e) {
            // 若文件不存在或读取失败，直接抛出运行时异常，避免后续空指针
            throw new RuntimeException("加载数据库配置文件失败，请检查 db.properties 是否存在！", e);
        } finally {
            // 确保输入流被关闭，防止内存泄漏
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }

        /* 从 Properties 容器中取出 key 对应的 value，
         * 并赋值给静态变量，供整个应用运行期间使用
         */
        driver   = properties.getProperty("driver");
        url      = properties.getProperty("url");
        username = properties.getProperty("username");
        password = properties.getProperty("password");
    }

    //获得数据库的连接
    public static Connection getConnection() {
        Connection conn = null;
        try {
            //连接驱动
            Class.forName(driver);
            //创建数据库
            conn = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return conn;
    }

    //编写查询公共类
    public static ResultSet execute(Connection conn, PreparedStatement preparedStatement,ResultSet resultSet, String sql,Object[] params) throws SQLException {
        //预编译的sql，在后面直接执行就可以了
        preparedStatement = conn.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            //setObject,占位符从1开始，但是我们的数组是从0开始
            preparedStatement.setObject(i + 1, params[i]);
        }
        resultSet = preparedStatement.executeQuery();
        return resultSet;
    }

    //编写增删改公共方法
    public static int execute(Connection conn, PreparedStatement preparedStatement, String sql,Object[] params)
            throws SQLException {
        //预编译的sql，在后面直接执行就可以了
        preparedStatement = conn.prepareStatement(sql);
        for (int i = 0; i < params.length; i++) {
            //setObject,占位符从1开始，但是我们的数组是从0开始
            preparedStatement.setObject(i + 1, params[i]);
        }
        int updateRow = preparedStatement.executeUpdate();
        return updateRow;
    }

    //释放资源 (要符合先开后关)
    public static boolean closeResource(Connection conn,
                                        PreparedStatement preparedStatement,
                                        ResultSet resultSet)
    {
        boolean flag = true;
        if (resultSet != null) {
            try {
                resultSet.close();
                //GC回收
                resultSet = null;
            } catch (SQLException e) {
                flag = false;
                throw new RuntimeException(e);
            }
        }
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
                //GC回收
                preparedStatement = null;
            } catch (SQLException e) {
                flag = false;
                throw new RuntimeException(e);
            }
        }
        if (conn != null) {
            try {
                conn.close();
                //GC回收
                conn = null;
            } catch (SQLException e) {
                flag = false;
                throw new RuntimeException(e);
            }
        }
        return flag;
    }


}
